using System.Collections.Generic;
using System.Text;
using GameStateManagement.Model;
using GameStateManagement.Model.Entities;
using GameStateManagement.View.Rendering;
using Microsoft.Xna.Framework;
using System.Xml.Serialization;
using GameStateManagement.Model.Physics;

namespace GameStateManagement.GravityWorld
{
    public enum GravityGameState
    {
        Paused,
        PickupFairy,
        MoveFairy,
        InFlight,
        Quiting,
    };

    [XmlRootAttribute(ElementName = "GravityModel", IsNullable = false)]
    [XmlInclude(typeof(MovingEntity))]
    [XmlInclude(typeof(StaticEntity))]
    public class GravityModel : GameModel
    {
        #region Fields

        
        private RenderManager _renderManager;
        private MovingEntity _theFairy;
        

        #endregion

        #region Constructors

        public GravityModel(RenderManager renderManager)
        {
            _renderManager = renderManager;
        }

        #endregion

        #region Public Methods

        #region Controler Methods

        private bool PickupFairy(Vector2 gesturePosition)
        {
            bool succeded = false;
            var fairyColData = _renderManager.GetCollisionData(_theFairy);
            if (fairyColData.BoundingBox.Contains((int)gesturePosition.X, (int)gesturePosition.Y))
            {
                ChangeGameState(GravityGameState.MoveFairy);
                succeded = true;
            }

            return succeded;
        }

        public bool MoveFairy(Vector2 position)
        {
            if (GameState == GravityGameState.MoveFairy
                || GameState == GravityGameState.PickupFairy && PickupFairy(position)
            )
            {
                position.X = MathHelper.Clamp(position.X, Map.StartPosition.X - 40, Map.StartPosition.X + 40);
                position.Y = MathHelper.Clamp(position.Y, Map.StartPosition.Y - 40, Map.StartPosition.Y + 40);

                _theFairy.Position = position;
            }
            return true;
        }

        public bool LetGoOfFairy(Vector2 position)
        {
            if (GameState == GravityGameState.MoveFairy)
            {
                var velocity = Vector2.Subtract(Map.StartPosition, position);
                _theFairy.Velocity = velocity / 10;

                ChangeGameState(GravityGameState.InFlight);
            }
            return false;
        }

        #endregion

        public override void Update(GameTime gameTime)
        {
            if (GameState == GravityGameState.InFlight)
            {
                base.Update(gameTime);
            }

            var msg = new StringBuilder();
            msg.AppendLine("Pos: ").Append((_theFairy).Position).Append(";\nVel: ").Append(_theFairy.Velocity);
            SetGameMessage(msg.ToString());
        }

        #endregion

        #region Initialization

        protected override void InitializeTextureNameList()
        {
            TextureNameList = new List<string>();
            foreach (var entity in Entities)
            {
                var renderable = entity as IRenderable;
                if (renderable != null)
                {
                    TextureNameList.Add(renderable.TextureName);
                }
            }
            foreach (var forceField in Physics.ForceFields)
            {
                var renderable = forceField as IRenderable;
                if (renderable != null)
                {
                    TextureNameList.Add(renderable.TextureName);
                }
            }
            foreach (var renderable in Decorations)
            {
                TextureNameList.Add(renderable.TextureName);
            }
        }

        public override void InitializeModel(bool forceReinisilaziton)
        {

            if (Entities == null || forceReinisilaziton)
            {
                Decorations = new List<Renderable>();
                Entities = new CompositeEntity();
                Physics = new PhysicsModule2D(_renderManager);

                LoadMap();
                InitializeTextureNameList();
            }
        }



        private void LoadMap()
        {
            Decorations.Add(new Renderable
            {
                Color = Color.White,
                Position = Vector2.Zero,
                Scale = new Vector2(1.5f, 1.5f),
                Rotation = 0,
                TextureName = Map.BackgroundTextureName
            });

            Decorations.Add(new Renderable
                                {
                                    Color = Color.White,
                                    Position = Map.StartPosition,
                                    Scale = Vector2.One,
                                    Rotation = 0,
                                    TextureName = "mountain"
                                });
            Decorations.Add(new Renderable
            {
                Color = Color.White,
                Position = Map.TargetPosition,
                Scale = Vector2.One,
                Rotation = 0,
                TextureName = "red_flower"
            });

            Decorations.AddRange(Map.Decorations);

            var theFairy = new MovingEntity(
                Map.StartPosition,
                Vector2.UnitY,
                "MS_Monster_Disinfect_Dwarf",
                Color.White,
                Vector2.One,
                1.0F)
            {
                Name = "TheFairy"
            };

            _theFairy = theFairy;

            Entities.AddChild(theFairy);

            foreach (var forceField in Map.ForceFields)
            {
                Physics.AddForceField(forceField);
            }

            foreach (var obstacle in Map.Obstacles)
            {
                Entities.AddChild(obstacle);
            }
        }

        #endregion
    }

}
